<?php

/*  Copyright 1999 by John Martin d/b/a www.ANYPORTAL.com       */
/*  All Rights Reserved.                                        */
/*                                                              */
/*  This software is freeware and is not in the public domain.  */
/*  You are hereby granted the right to freely distribute this  */
/*  software as long as this copyright notice remains in place. */
/*                                                              */
/*  Comments or suggestions?   email: andmore@alief.com         */
/*                                                              */
/*  This is the PHP port: AnyPortal(php)-0.1                    */
/*  ========================================                    */
/*                                                              */
/*  PHP version 2000 by Stefan@Wiesendanger.org                 */
/*  No Rights Reserved. What for, anyhow ?                      */
/*                                                              */
/*  Date       Remarks                                          */
/*  ---------  -----------------------------------------------  */
/*  25 MAY 99  original ASP version                             */     
/*  17 SEP 99  change upload from SA-FILEUP to aspSmartUpload   */
/*  10 APR 00  simplified PHP3 version                          */
/*  18 APR 00  most of PHP3 port working. Slight modifications  */
/*  22 APR 00  modified syntax highlighting, no absolute paths  */
/*             revealed, PHP builtin authentication, global     */
/*             style sheet as callback, use apache default      */
/*             icons as an alternative to the wingdings font.   */
/*  25 APR 00  catch some exceptions (not foolproof yet)        */
/*  26 APR 00  catch some more exceptions, implicit copy        */
/*             function by saving somewhere else in the detail  */
/*             view, MD5 hashed password.                       */
/*  27 APR 00  Fixed authentication bug                         */
/*  12 MAY 00  Fixed trouble with exec() with newer versions of */
/*             PHP3. Fixed bug which would send you to a non-   */
/*             existent address after file modifications.       */

/*

	This project is now called Directory Manager.

	For more info, please see web pages at
	http://www.rot13.org/~dpavlin/docman.html

	It's relased under GPL by
	Dobrica Pavlinusic <dpavlin@rot13.org>


IMPORTANT INSTALLATION NOTE:
	deny serving of .* (dot-something) files in web server!
	Otherwise, uses can access your log files, users and/or
	deleted files!

	.htusers is in form:
	login:Real Name:[md5(loginpassword)|auth_*]:email@host.dom


TODO:
	mixed file/directory output (add type to each entry,
		real support for links)
	access controll

*/

//////////////////////////////////////////////////////////////////

// TODO : Don't let the file be modified itself. Create a hash of 
// it (kinda hard since it's self-referential ;-). Make better use 
// of session management. Escapeshellcmd for all user input.

//////////////////////////////////////////////////////////////////

// GLOBAL PARAMETERS
// =================
// Make modifications here to suit docman to your needs

// 	error_reporting(4) ;		// how verbose ?

	// from where to include auth_*.php modules?
	$gblIncDir = "/home/httpd/docman";

	// username/password should not be system 
	// usernames/passwords !!

	$gblPw    = "";

	// date format
//	$gblDateFmt="D, F d, Y";
	$gblDateFmt="Y-m-d";

	// time format
//	$gblTimeFmt="g:i:sA";
	$gblTimeFmt="H:i:s";

	// Number of backup files to keep
	$gblNumBackups=3;

	// show red star if newer than ... days
	$gblModDays=1;

	// choose GifIcon below unless you have the M$
	// WingDings font installed on your system

	$gblIcon="GifIcon";		// MockIcon or GifIcon

	// the directory below should be /icons/ or /icons/small/ 
	// on Apache; a set of icons is included in the distribution

	$gblIconLocation="/icons/"; 

	// files you want to be able to edit in text mode
	// and view with (primitive) syntax highlighting

	$gblEditable = array( ".txt",".asa",".asp",".htm",".html",
	                      ".cfm",".php3",".php",".phtml",
	                      ".shtml",".css" ) ;

	// files that will display as images on the detail page
	// (useless if your browser doesn't support them)

	$gblImages   = array( ".jpg",".jpeg",".gif",".png",".ico",
	                      ".bmp",".xbm") ;

	// which files to hide (separated by ,)
	$gblHide = "";

	// Where are users? (by default in .htusers file)
	$gblUsers = "htusers_file";

//////////////////////////////////////////////////////////////////

function StartHTML($title,$text="") {

	$title = "Document Manager " . $title ;
	$host  = $GLOBALS["HTTP_HOST"] ;
	$self  = $GLOBALS["PHP_SELF"] ;
?>

<HTML>
<HEAD>
 <TITLE><?= $host . " " . $title ?></TITLE>
 <META NAME="description" CONTENT="PHP port of AnyPortal Site Manager">
 <META NAME="keywords" CONTENT="site manager, web site maintenance">
 <META NAME="robots" CONTENT="noindex">
 <META HTTP-EQUIV="expires" CONTENT="0">
 <LINK REL="stylesheet" TYPE="text/css" 
	HREF="<?= $self ?>?STYLE=get">
</HEAD>
<BODY BGCOLOR="#FFFFFF">
 <H3 ALIGN="RIGHT"><?= $host ?></H3>
<TABLE BORDER=0 WIDTH="100%"><TR>
 <TD CLASS=INV><?= $title ?></TD></TR></TABLE>
 <P><?= $text ?></P>

<?php 
} // end function StartHTML

//////////////////////////////////////////////////////////////////

function EndHTML() {
?>

<HR>
<P CLASS=FTR>
<B><?= date($GLOBALS[gblDateFmt]) ?> -
<?= date($GLOBALS[gblTimeFmt]) ?> -
<?= $GLOBALS[gblUserName] ?>
<small> [<a href="<?= $GLOBALS["PHP_SELF"] ?>?relogin=<?= $GLOBALS[gblPw] ?>">logout</a>]</small>
</B>
<BR>ANYPORTAL(php) Site Manager 
<br><small>
&copy; 1999 by <A HREF="http://www.anyportal.com">ANYPORTAL</A>,
&copy; 2000 by <A HREF="http://da.nger.org">d@nger.org</A>,
&copy; 2000 by <A HREF="http://www.rot13.org/~dpavlin/">DbP</A>
</small>
</P>
<BR>
<? //include(".debug.inc") ?>
<BR><BR></BODY></HTML>

<?php
} // end function EndHTML

//////////////////////////////////////////////////////////////////

function CSS() {
?>

BODY,TD,P,H1,H2,H3 { font-family:Verdana,Helvetica,Arial,sans-serif; }
.BLK { color:black; }
.RED { color:red; }
.TOP { color:red; font-size:70%; } /* table headings */
.INV { color:white; background-color:navy; 
	font-weight:bold; font-size:120%; } /* title */
.FTR { } /* footer */
.LST { background-color:#E0E0E0; } /* table cells */
.BAR { background-color:#E0E0E0; } /* action bar */
PRE { color:blue; font-family:Lucida Console,Courier New,
	Courier,sans-serif; } /* source code */
EM { color:green; font-style:normal; } /* line numbers */
.REM { color:silver; }
.XML { color:navy; background-color:yellow; }
.MCK { color:red; font-family:WingDings; } /* Mock Icons */
A:HOVER { color:red; }

<?php
} // end function CSS

//////////////////////////////////////////////////////////////////

function DetailPage($fsRoot,$relDir,$fn) {
	
	global $gblEditable, $gblImages, $webRoot ;
	$self = $GLOBALS["PHP_SELF"] ;

	$relPath  = $relDir . "/" . $fn ;
	$fsPath   = $fsRoot . $relPath ;
	$fsDir    = $fsRoot . $relDir ;

	$exists   = file_exists($fsPath) ;
	$ext      = strtolower(strrchr($relPath,".")) ;
	$editable = ( $ext=="" || strstr(join(" ",$gblEditable),$ext)) ;
	$writable = is_writeable($fsPath) ;
	$file_lock = CheckLock($fsPath);

	if (!$editable && !$exists) 
		Error("Creation unsupported for type",$relPath) ;
	if (!exists && !is_writeable($fsDir) )
		Error("Creation denied",$relDir) ;

	$text  = "Use this page to view, modify or " ;
	if (is_dir($fsPath)) {
		$text .="delete a directory on this " ;
	} else {
		$text .= "delete a single document on this " ;
	};
	$text .= "web site." ;	
	$title = "(Detail Page)" ;
	StartHTML($title, $text) ;

	echo "<H3>" . $relDir . "/" . $fn . "</H3>" ;
	if ($exists) {  // get file info
		$fsize = filesize($fsPath) ; 
		$fmodified = date("$GLOBALS[gblDateFmt] $GLOBALS[gblTimeFmt]", filemtime($fsPath)) ;
		$faccessed = date("$GLOBALS[gblDateFmt] $GLOBALS[gblTimeFmt]", fileatime($fsPath)) ;
		$fuid=fileowner($fsPath);
		$fgid=filegroup($fsPath);
		$userinfo = posix_getpwuid($fuid);
		$grpinfo = posix_getgrgid($fgid);
		echo "<PRE>";
		if (!is_dir($fsPath)) echo "    file size: " . $fsize . " Bytes<BR>" ;
		echo "last modified: <B>" . $fmodified . "</B><BR>" ;
		echo "last accessed: <B>" . $faccessed . "</B><BR>" ;
		echo "        owner: <B>" . $userinfo["name"] . " [$fuid]</B><BR>" ;
		echo "        group: <B>" . $grpinfo["name"] . " [$fgid]</B><BR>" ;
		echo "  permissions: <B>" ; 
		echo printf( "%o", fileperms($fsPath) ) . "</B>" ;
		echo "</PRE>" ;

	}

	if ( !is_dir($fsPath) && $editable && ($writable || !$exists) && !$file_lock ) { 
		$fh = fopen($fsPath,"a+") ;
		rewind($fh) ;
		$fstr = fread($fh,filesize($fsPath)) ;
		fclose($fh) ;
		$fstr = htmlentities( $fstr ) ;
?>

<FORM ACTION="<?= $self ; ?>" METHOD="POST">
<SPAN TITLE="Click [SAVE] to store updated contents.">
	<B>DOCUMENT CONTENTS</B>
</SPAN><BR>
<TEXTAREA NAME="FILEDATA" ROWS=18 COLS=70 WRAP="OFF"><?php 
echo($fstr) ; ?></TEXTAREA>
<INPUT TYPE="HIDDEN" NAME="DIR" VALUE="<?= $relDir ; ?>">
<INPUT TYPE="HIDDEN" NAME="FN" VALUE="<?= $fn ; ?>">
<INPUT TYPE="HIDDEN" NAME="POSTACTION" VALUE="SAVE">
<INPUT TYPE="HIDDEN" SIZE=48 MAXLENGTH=255 NAME="RELPATH" 
	VALUE="<?= $relPath ; ?>">
<br>
<INPUT TYPE="RESET" VALUE="UNDO ALL CHANGES">
<INPUT TYPE="SUBMIT" VALUE="SAVE">
</FORM>

<?php
	}
	if ( !$file_lock && $ext!="" && strstr(join(' ',$gblImages),$ext) ) {  
		$info  = getimagesize($fsPath) ;
		$tstr = "<IMG SRC=\"$webRoot".urlpath($relPath)."\" BORDER=0 " ;
		$tstr .= $info[3] . " ALT=\"" . $fn . " - " ;
		$tstr .= (int)(($fsize+1023)/1024) . "Kb\">" ;
//		echo htmlentities($tstr) . "<BR><BR>" . $tstr ;
		echo $tstr ;
	}

?>

<FORM ACTION="<?= $self ; ?>" METHOD="POST">
<INPUT TYPE="HIDDEN" NAME="DIR" VALUE="<?= $relDir ; ?>">
<INPUT TYPE="HIDDEN" NAME="FN" VALUE="<?= $fn ; ?>">
<INPUT TYPE="SUBMIT" NAME="POSTACTION" VALUE="CANCEL"><BR>

<?php

	if ($file_lock) {
?>
<hr>
<SPAN TITLE="Check OK and click UNLOCK to remove lock on file.">
<B>OK TO FORCE LOCK REMOVAL ON "<?= $fn ; ?>" HELD BY <?= $file_lock ?>? </B></SPAN>
<INPUT TYPE="CHECKBOX" NAME="CONFIRM">
<INPUT TYPE="SUBMIT" NAME="POSTACTION" VALUE="UNLOCK">
<?
	} // file_lock

	if (substr($fn,0,4) == ".del") {
		$action="UNDELETE";
		$desc="undelete previously deleted file";
	} else {
		$action="DELETE";
		$desc="delete";
	}

	if ($exists && $writable) {
?>

<HR>
<a name="undelete">
<SPAN TITLE="Check OK and click [<?= $action ?>] to <?= $desc ?>.">
<B>OK TO <?= $action ?> "<?= $fn ; ?>"? </B></SPAN>
<INPUT TYPE="CHECKBOX" NAME="CONFIRM">
<INPUT TYPE="SUBMIT" NAME="POSTACTION" VALUE="<?= $action ?>">

<HR>
<a name="rename">
<SPAN TITLE="Check OK and click [RENAME] to rename.">
<B>OK TO RENAME "<?= $fn ; ?>" TO 
<INPUT TYPE="TEXT" SIZE=24 MAXLENGTH=255 NAME="NEWNAME" VALUE="<?= $fn ?>">
? </B></SPAN>
<INPUT TYPE="CHECKBOX" NAME="CONFIRM">
<INPUT TYPE="SUBMIT" NAME="POSTACTION" VALUE="RENAME">

<?php
	}	// exists && writable
?>
<HR>
<a name="note">
<B>NOTE FOR "<?= $fn ; ?>":
<INPUT TYPE="TEXT" SIZE=50 MAXLENGTH=255 NAME="NOTE" VALUE="<?= ReadNote($fsPath) ?>">
</B></SPAN>
<INPUT TYPE="SUBMIT" NAME="POSTACTION" VALUE="NOTE">

</FORM>

<?php

	$name=basename("$fsDir/$fn");
	$logname=dirname("$fsDir/$fn")."/.log/$name";
	$bakdir=dirname("$fsDir/$fn")."/.bak";
	if (file_exists($logname)) {
		$log=fopen($logname,"r");
		$cl1=" class=LST"; $cl2="";
		$logarr = array();
		while($line = fgetcsv($log,255,"\t")) {
			$cl=$cl1; $cl1=$cl2; $cl2=$cl;
			array_unshift($logarr,array($cl,$line[0],$line[1],$line[2],$line[3]));
		}
		fclose($log);
		if (is_dir("$fsDir/$fn")) {
			$whatis="DIRECTORY";
		} else {
			$whatis="FILE";
		}
		print "<hr><br><b>CHANGES TO THIS $whatis</b><br><table border=0 width=100%>\n";
		$bakcount = 0;	// start from 0, skip fist backup (it's current)
		while ($e = array_shift($logarr)) {
			if (strstr($e[4],"upload")) {
				if (file_exists("$bakdir/$bakcount/$name")) {
					$e[4]="<a href=\"$webRoot".urlpath(dirname($relPath)."/.bak/$bakcount/$name")."\">$e[4]</a>";
				}
				$bakcount++;
			}
			print "<tr><td$e[0]>$e[1]</td><td$e[0]>$e[2]</td><td$e[0]>$e[3]</td><td$e[0]>$e[4]</td></tr>\n";
		}
		print "</table>";
	}

	EndHTML() ;

} // end function DetailPage

//////////////////////////////////////////////////////////////////

function DisplayCode($fsRoot,$relDir,$fn) {

	$path = $fsRoot . $relDir . "/" . $fn ;

	if (!file_exists($path)) Error("File not found",$path) ;

	StartHTML("(".$relDir."/".$fn.")","");

	$tstr = join("",file($path)) ;
	$tstr = htmlentities($tstr) ;

	// Tabs
	$tstr = str_replace(chr(9),"   ",$tstr) ;  

	// ASP tags & XML/PHP tags
	$aspbeg = "<SPAN CLASS=XML>&lt;%</SPAN><SPAN CLASS=BLK>" ;
	$aspend = "</SPAN><SPAN CLASS=XML>%&gt;</SPAN>" ;
	$tstr = str_replace("&lt;%",$aspbeg,$tstr) ;
	$tstr = str_replace("%&gt;",$aspend,$tstr) ; 	

	$xmlbeg = "<SPAN CLASS=XML>&lt;?</SPAN><SPAN CLASS=BLK>" ;
	$xmlend = "</SPAN><SPAN CLASS=XML>?&gt;</SPAN>" ;
	$tstr = str_replace("&lt;?",$xmlbeg,$tstr) ;
	$tstr = str_replace("?&gt;",$xmlend,$tstr) ; 	

	// C style comment
	$tstr = str_replace("/*","<SPAN CLASS=REM>/*",$tstr) ; 	
	$tstr = str_replace("*/","*/</SPAN>",$tstr) ; 			

	// HTML comments
	$tstr = str_replace("&lt;!--","<I CLASS=RED>&lt;!--",$tstr) ;  
	$tstr = str_replace("--&gt;","--&gt;</I>",$tstr) ;  

	echo "<PRE>" ;	

	$tstr = split("\n",$tstr) ;
	for ($i = 0 ; $i < sizeof($tstr) ; ++$i) {
		// add line numbers
		echo "<BR><EM>" ;
		echo substr(("000" . ($i+1)), -4) . ":</EM> " ;
		$line = $tstr[$i] ;
		// C++ style comments
		$pos = strpos($line,"//") ;
		// exceptions: two slashes aren't a script comment
		if (strstr($line,"//") &&
		    ! ($pos>0 && substr($line,$pos-1,1)==":") &&
		    ! (substr($line,$pos,8) == "//--&gt;") &&
		    ! (substr($line,$pos,9) == "// --&gt;")) {
		 $beg = substr($line,0,strpos($line,"//")) ;
		 $end = strstr($line,"//") ;
		 $line = $beg."<SPAN CLASS=REM>".$end."</SPAN>";
		}
		// shell & asp style comments
		$first = substr(ltrim($line),0,1) ;
		if ($first == "#" || $first == "'") {
		 $line = "<SPAN CLASS=REM>".$line."</SPAN>";
		}
		print($line) ;
	} // next i

	echo "</PRE>" ;
		
	EndHTML() ;

} // end function DisplayCode

//////////////////////////////////////////////////////////////////

function MockIcon($txt) {
	$tstr = "<SPAN CLASS=MCK>" ;

	switch (strtolower($txt)) {
	case ".bmp" :
	case ".gif" :
	case ".jpg" :
	case ".jpeg":
	case ".tif" :
	case ".tiff":
		$d = 176 ;
		break ;
	case ".doc" :
		$d = 50 ;
		break ;
	case ".exe" :
	case ".bat" :
		$d = 255 ;
		break ;
	case ".bas" :
	case ".c"   :
	case ".cc"  :
	case ".src" :
		$d = 255 ;
		break ;
	case "file" :
		$d = 51 ;
		break ;
	case "fldr" :
		$d = 48 ;
		break ;
	case ".htm" :
	case ".html":
	case ".asa" :
	case ".asp" :
	case ".cfm" :
	case ".php3":
	case ".php" :
	case ".phtml" :
	case ".shtml" :
		$d = 182 ;
		break ;
	case ".pdf" :
		$d = 38 ;
		break;
	case ".txt" :
	case ".ini" :
		$d = 52 ;
		break ;
	case ".xls" :
		$d = 252 ;
		break ;
	case ".zip" :
	case ".arc" :
	case ".sit" :
	case ".tar" :
	case ".gz"  :
	case ".tgz" :
	case ".Z"   :
		$d = 59 ;
		break ;
	case "view" :
		$d = 52 ;
		break ;
	case "up" :
		$d = 199 ;
		break ;
	case "blank" : 
		return "&nbsp;&nbsp;</SPAN>" ;
		break ;
	default :
		$d = 51 ;
	}

	return $tstr . chr($d) . "</SPAN>" ;
} // end function MockIcon

//////////////////////////////////////////////////////////////////

function GifIcon($txt) {
	global $gblIconLocation ;

	switch (strtolower($txt)) {
	case ".bmp" :
	case ".gif" :
	case ".jpg" :
	case ".jpeg":
	case ".tif" :
	case ".tiff": 
		$d = "image2.gif" ;
		break ;
	case ".doc" :
		$d = "layout.gif" ;
		break ;
	case ".exe" :
	case ".bat" :
		$d = "screw2.gif" ;
		break ;
	case ".bas" :
	case ".c"   :
	case ".cc"  :
	case ".src" :
		$d = "c.gif" ;
		break ;
	case "file" :
		$d = "generic.gif" ;
		break ;
	case "fldr" :
		$d = "dir.gif" ;
		break ;
	case ".phps" :
		$d = "phps.gif" ;
		break ;
	case ".php3" :
		$d = "php3.gif" ;
		break ;
	case ".htm" :
	case ".html":
	case ".asa" :
	case ".asp" :
	case ".cfm" :
	case ".php3":
	case ".php" :
	case ".phtml" :
	case ".shtml" :
		$d = "world1.gif" ;
		break ;
	case ".pdf" :
		$d = "pdf.gif" ;
		break;
	case ".txt" :
	case ".ini" :
		$d = "text.gif" ;
		break ;
	case ".xls" :
		$d = "box2.gif" ;
		break ;
	case ".zip" :
	case ".arc" :
	case ".sit" :
	case ".tar" :
	case ".gz"  :
	case ".tgz" :
	case ".Z"   :
		$d = "compressed.gif" ;
		break ;
	case "view" :
		$d = "index.gif" ;
		break ;
	case "up" :
		$d = "back.gif" ;
		break ;
	case "blank" : 
		$d = "blank.gif" ;
		break ;
	case "checkout":
		$d = "box2.gif";
		break;
	case "checkin":
		$d = "hand.up.gif";
		break;
	case "locked":
		$d = "screw2.gif";
		break;
	case "note":
		$d = "quill.gif";
		break;
	default :
		$d = "generic.gif" ;
	}

	return "<IMG SRC=\"$gblIconLocation" . $d . "\" BORDER=0>" ;
} // end function GifIcon

//////////////////////////////////////////////////////////////////

function Navigate($fsRoot,$relDir) {

	global $gblEditable, $gblIcon, $gblModDays, $webRoot, $gblHide ;

	$self     = $GLOBALS["PHP_SELF"] ;

	$fsDir = $fsRoot . $relDir . "/" ; // current directory

	if (!is_dir($fsDir)) Error("Dir not found",$relDir) ; 

	$hide_items=",$gblHide,";

	// read directory contents
	if ( !($dir = @opendir($fsDir)) ) 
		Error("Read Access denied",$relDir) ;
	while ($item = readdir($dir)) {
		if ( substr($item,0,1) == "." || strstr($hide_items,",$item,") ) continue ;
		if ( is_dir($fsDir . $item) ) {
			$dirList[] = $item ;
		} else if ( is_file($fsDir . $item) ) {
			$fileList[] = $item ;		
		} else if ( is_link($fsDir . $item) ) {
			$dirList[] = $item ;
		} else {
		  // unknown file type
		  // $text = "Could not determine file type of " ;
		  // Error("File Error", $text.$relDir."/".$item) ;
		  // exit ;
		}
	}
	closedir($dir) ; 

	// scan deleted files
	if ( $GLOBALS[show_deleted] == 1 && ($dir = @opendir("$fsDir/.del")) ) {
		while ($item = readdir($dir)) {
			if ( substr($item,0,1) == "." || strstr($hide_items,",$item,") ) continue ;
			$fileList[] = ".del/$item" ;		
		}
		closedir($dir) ; 
	}

	$emptyDir = ! (sizeof($dirList) || sizeof($fileList)) ;

	// start navigation page
	$text  = "Use this page to add, delete";
	if (! isset($show_deleted)) {
		$text .= ", <a href=$self?D=".urlencode($relDir)."&show_deleted=1>undelete</a>";
	}
	$text .= " or revise files on this web site." ;
	$text .= "<br>Examine list of files <a href=\"$self?A=Ch1\">changed in last day</a> or <a href=\"$self?A=Ch\">all changes</a>.";
	StartHTML("(Navigate)",$text) ;

	echo "<TABLE BORDER=0 CELLPADDING=2 
		CELLSPACING=3 WIDTH=\"100%\">" ;

	// updir bar	
	if ($fsDir != $fsRoot) {
		$parent = dirname($relDir) ;
		if ($parent == "") $parent = "/" ;
?>

<TR><TD><?= $gblIcon("up") ?></TD><TD COLSPAN=5 CLASS=LST>
<A HREF="<?= $self ?>?D=<?= urlencode($parent) ?>">
<B><?= $parent ?></B></A></TD></TR>

<?php
	}

function plural($name,$count) {
	$out="$count $name";
	if ($count > 1) {
		$out.="s";
	}
	return $out;
}

	// output subdirs
	if (sizeof($dirList) > 0) {
		sort($dirList) ; 
?>

<TR><TD></TD><TD COLSPAN=2 CLASS=TOP>DIRECTORY NAME (<?= plural("dir",sizeof($dirList)) ?>)</TD><TD COLSPAN=3 CLASS=TOP>DIRECTORY NOTE</TR>

<?php
		while (list($key,$dir) = each($dirList)) {

			$info_url=$self."?A=E&F=".urlencode($dir)."&D=".urlencode($relDir);
			$tstr = "<A HREF=\"" . $self . "?D=" ; 
			$tstr .= urlencode($relDir."/".$dir) ;
			$tstr .= "\">" . $dir . "/</A>" ;
			$note_html="<a href=\"$info_url#note\">".$gblIcon("note")."</a>".ReadNote($fsDir.$dir);
?>

<TR><TD>
<A HREF="<?= $info_url ?>" TITLE="View/Edit">
<?= $gblIcon("fldr") ?></A></TD>
<TD COLSPAN=2 CLASS=LST><?= $tstr ?></TD>
<TD COLSPAN=3 CLASS=LST><?= $note_html ?></TD></TR>

<?php
		}  // iterate over dirs
	}  // end if no dirs
?>

<TR><TD></TD><TD COLSPAN=5><HR><B><?= $webRoot . $relDir ?>
</B></TD></TR>
<TR><TD></TD><TD CLASS=TOP>DOCUMENT NAME (<?= plural("file",sizeof($fileList)) ?>)</TD>
<TD><?= $gblIcon("blank").$gblIcon("blank") ?></TD>
<TD CLASS=TOP>NOTE</TD>
<TD CLASS=TOP>LAST UPDATE</TD><TD CLASS=TOP>FILE SIZE</TD></TR>

<?php
	if (sizeof($fileList) > 0) {
	  sort($fileList) ;
	  while (list($key,$file) = each($fileList)) {	
		$path = $fsDir."/".$file ;
		$mod  = filemtime($path) ;
		$sz   = filesize($path) ;

		if ($sz >= 10240) {
			$sz = (int)(($sz+1023)/1024) . " k" ;
		} else {
			$sz .= " " ;
		} // end size

		$a = $b = "" ;

		$info_url=$self."?A=E&F=".urlencode($file)."&D=".urlencode($relDir);

		if ( ($mod + $gblModDays*86400) > time() ) {
			$a  = "<SPAN CLASS=RED TITLE=\"Newer" ;
			$a .= " than $gblModDays days\"> * </SPAN>" ;
		}

		$file_lock=CheckLock($path);

		$file_url_html="<A HREF=\"$self?A=V&F=".urlencode($file);
		$file_url_html.="&D=".urlencode($relDir);
		$file_url_html.="\" TITLE=\"View file\">" ;

		if (substr($file,0,5) != ".del/") {
			$file_url_html .= $file . "</A>" . $a ;
		} else {
			$file_url_html .= substr($file,5,strlen($file)-5) . "</a> <SPAN CLASS=RED TITLE=\"deleted\"> <a href=\"$info_url#undelete\">deleted</a> </span>";
		}

		$note_html="<a href=\"$info_url#note\">".$gblIcon("note")."</a>".ReadNote($path);

		$ext = strtolower(strrchr($file,".")) ;

		if ($file_lock) {
			if ($file_lock == $GLOBALS[gblUserName]) {
				$b.="<A HREF=\"$self?A=Ci&F=".urlencode($file);
				$b.="&D=".urlencode($relDir);
				$b.="\" TITLE=\"Checkin (update) file on server\">" ;
				$file_url_html=$b;
				$b.=$gblIcon("checkin")."</A>" ;
				$b.= $gblIcon("blank");
				$file_url_html.="$file</a> $a";
				$note_html = $gblIcon("blank")."<b>Please check-in (update) this file</b>";
			} else {
				$b = $gblIcon("locked");
				$b.= $gblIcon("blank");
				$note_html = $gblIcon("blank")."<b>File locked by $file_lock</b>";
				$file_url_html = "$file $a";
			}
		} else {
			$b.="<A HREF=\"$self?A=Co&F=".urlencode($file);
			$b.="&D=".urlencode($relDir);
			$b.="\" TITLE=\"Checkout file for edit\">" ;
			$b.=$gblIcon("checkout")."</A>" ;

			if ( $ext=="" || strstr(join(" ",$gblEditable),$ext) ) {  
				$b.="<A HREF=\"$self?A=C&F=".urlencode($file);
				$b.="&D=".urlencode($relDir);
				$b.="\" TITLE=\"List contents\">" ;
				$b.=$gblIcon("view")."</A>" ;
			} else {
				$b.= $gblIcon("blank");
			}
		}


?>

<TR><TD>
<A HREF="<?= $info_url ?>" TITLE="View/Edit">
<?= $gblIcon($ext) ?></A></TD>
<TD CLASS=LST><?= $file_url_html ?></TD>
<TD CLASS=LST ALIGN=center><?= $b ?></TD>
<TD CLASS=LST ALIGN=left><?= $note_html ?></TD>
<TD CLASS=LST><?= date("$GLOBALS[gblDateFmt] $GLOBALS[gblTimeFmt]",$mod) ?></TD>
<TD CLASS=LST><?= $sz ?>Bytes</TD></TR>

<?php
	  }  // iterate over files
	} else {  // end if no files
?>
 <TR><TD></TD><TD COLSPAN=5 CLASS=LST>
  No files in this directory
 </TD></TR>
<?
	}

	if ($emptyDir) {
?>

<FORM METHOD="POST" ACTION="<?= $self ?>">
 <TR><TD></TD><TD COLSPAN=5 CLASS=BAR>
  <INPUT TYPE="HIDDEN" NAME="DIR" VALUE="<?= $relDir ?>">
  OK TO DELETE THIS EMPTY FOLDER?
  <INPUT TYPE="CHECKBOX" NAME="CONFIRM"> 
  <INPUT TYPE="SUBMIT" NAME="POSTACTION" VALUE="DELETE">
 </TD></TR>
</FORM>

<?php
	} // end if emptyDir
?>

<TR><TD></TD><TD COLSPAN=5><HR></TD></TR>

<?
if (file_exists(".info.inc")) {
	print "<TR><TD></TD><TD COLSPAN=5>";
	include(".info.inc");
	print "</TD></TR>
	<TR><TD></TD><TD COLSPAN=5><HR></TD></TR>";
}
?>

<FORM METHOD="POST" ACTION="<?= $self ?>">
<TR><TD></TD><TD COLSPAN=5 CLASS=BAR>CREATE NEW
 <INPUT TYPE="RADIO" NAME="T" VALUE="D" CHECKED>DIRECTORY -OR- 
 <INPUT TYPE="RADIO" NAME="T" VALUE="F">FILE : &nbsp;&nbsp;
 <NOBR>NAME <INPUT TYPE="TEXT" NAME="FN" SIZE=14>
 <INPUT TYPE="HIDDEN" NAME="POSTACTION" VALUE="CREATE">
 <INPUT TYPE="HIDDEN" NAME="DIR" VALUE="<?= $relDir ?>">
 <INPUT TYPE="SUBMIT" VALUE="CREATE" NAME="CREATE">
 </NOBR> 
 <NOBR>OR <A HREF="<?= $self ?>?A=U&D=<?= urlencode($relDir) ?>">UPLOAD</A> A FILE
 </NOBR>
</TD></TR>
</FORM>
</TABLE>

<?php
	EndHTML() ;
} // end function Navigate

//////////////////////////////////////////////////////////////////

function UploadPage($fsRoot, $relDir, $filename="") {

	$self = $GLOBALS["PHP_SELF"] ;
	if ($relDir == "") $relDir = "/" ; 
?>

<P><TABLE BORDER=0 CELLPADDING=5><TR><TD WIDTH=5></TD><TD CLASS=BAR>
<FORM ENCTYPE="multipart/form-data" METHOD="POST" 
 ACTION="<?= $self ?>">
DESTINATION DIRECTORY:<B><?= " " . $relDir ?></B>
<? if (isset($filename) && $filename!="") { ?>
<br>DESTINATION FILE:<B><?= " " . $filename ?></B>
<INPUT TYPE="HIDDEN" NAME="FILENAME" VALUE="<?= $filename ?>">
<? } ?>
<P>PATHNAME OF LOCAL FILE<BR>
<INPUT TYPE="HIDDEN" NAME="DIR" VALUE="<?= $relDir ?>">
<INPUT TYPE="HIDDEN" NAME="POSTACTION" VALUE="UPLOAD">
<INPUT SIZE=30 TYPE="FILE" NAME="FN"></P>
<P><INPUT TYPE="SUBMIT" VALUE="UPLOAD"></P>
<P>If the <B>[BROWSE...]</B> button is not displayed,<BR>
you must upgrade to an RFC1867-compliant browser.</P>
<P>Your browser:<BR><?= $GLOBALS["HTTP_USER_AGENT"] ?></P>
</FORM>
</TD></TR>
<TR><TD></TD><TD>
<FORM METHOD="POST" ACTION="<?= $self ?>">
<INPUT TYPE="HIDDEN" NAME="DIR" VALUE="<?= $relDir ?>"><BR>
<INPUT TYPE="SUBMIT" NAME="POSTACTION" VALUE="CANCEL">
</FORM>
</TD></TR></TABLE></P>

<?php	
} // end function UploadPage

//////////////////////////////////////////////////////////////////

function Error($title,$text="") {
	StartHTML("(".$title.")",$text) ;
	echo "<P ALIGN=center>Hit your Browser's Back Button.</P>" ;
	EndHTML() ;
	exit ;
} // end function Error

//////////////////////////////////////////////////////////////////

function NoEntry() {

	$user = $GLOBALS["PHP_AUTH_USER"] ;
	$pw   = $GLOBALS["PHP_AUTH_PW"] ;	
	$self = $GLOBALS["PHP_SELF"] ;

	$title = "(401 Unauthorized)" ;
	$text  = "No trespassing !" ;
	StartHTML($title,$text) ;

	EndHTML() ;
	exit ;
}

//////////////////////////////////////////////////////////////////

function LogIt($target,$msg) {

	$dir=dirname($target);
	if (! file_exists($dir."/.log")) {
		mkdir($dir."/.log",0700);
	}
	$file=basename($target);

	$log=fopen("$dir/.log/$file","a+");
	fputs($log,date("$GLOBALS[gblDateFmt]\t$GLOBALS[gblTimeFmt]").
		"\t$GLOBALS[gblUserName]\t$msg\n");
	fclose($log);

}


//////////////////////////////////////////////////////////////////

function WriteNote($target,$msg) {

	$target=stripSlashes($target);
	$dir=dirname($target);
	if (! file_exists($dir."/.note")) {
		mkdir($dir."/.note",0700);
	}
	$file=basename($target);

	$note=fopen("$dir/.note/$file","w");
	fputs($note,"$msg\n");
	fclose($note);

	Logit($target,"added note $msg");

}

function ReadNote($target) {

	$target=stripSlashes($target);
	$dir=dirname($target);
	$file=basename($target);
	$msg="";
	if (file_exists($dir."/.note/$file")) {
		$note=fopen("$dir/.note/$file","r");
		$msg=fgets($note,4096);
		fclose($note);
	}
	return HtmlSpecialChars(StripSlashes($msg));

}

//////////////////////////////////////////////////////////////////

function MoveTo($source,$folder) {

	$source=stripSlashes($source);
	$file=basename($source);
	if (! file_exists($folder)) {
		mkdir($folder,0700);
	}
	if (file_exists($source)) {
		rename($source,"$folder/$file");
	}
}

//////////////////////////////////////////////////////////////////

function Lock($target) {

	$target=stripSlashes($target);
	$dir=dirname($target);
	if (! file_exists($dir."/.lock")) {
		mkdir($dir."/.lock",0700);
	}
	$file=basename($target);

	if (file_exists("$dir/.lock/$file")) {
		Logit($target,"attempt to locked allready locked file!");
	} else {
		$lock=fopen("$dir/.lock/$file","w");
		fputs($lock,"$GLOBALS[gblUserName]\n");
		fclose($lock);

		Logit($target,"file locked");
	}

}

function CheckLock($target) {

	$target=stripSlashes($target);
	$dir=dirname($target);
	$file=basename($target);
	$msg=0;
	if (file_exists($dir."/.lock/$file")) {
		$lock=fopen("$dir/.lock/$file","r");
		$msg=fgets($lock,4096);
		fclose($lock);
	}
	return chop($msg);

}

function Unlock($target) {

	$target=stripSlashes($target);
	$dir=dirname($target);
	$file=basename($target);
	if (file_exists($dir."/.lock/$file")) {
		unlink("$dir/.lock/$file");
		Logit($target,"file unlocked");
	} else {
		Logit($target,"attempt to unlocked non-locked file!");
	}

}

//////////////////////////////////////////////////////////////////

function urlpath($url) {
	$url=urlencode(StripSlashes("$url"));
	$url=str_replace("%2F","/",$url);
	$url=str_replace("+","%20",$url);
	return($url);
}

//////////////////////////////////////////////////////////////////

function safe_rename($fromdir,$fromfile,$tofile) {
	function try_rename($from,$to) {
#		print "$from -> $to\n";
		if (file_exists($from) && is_writeable(dirname($to))) {
			rename($from,$to);
		}
	}

	function try_dir($todir) {
		if (! file_exists($todir)) {
			mkdir($todir,0700);
	        }
	}

	$to="$fromdir/$tofile";
	$todir=dirname($to);
	$tofile=basename($to);

#	print "<pre>$fromdir / $fromfile -> $todir / $tofile\n\n";

	try_rename("$fromdir/$fromfile","$todir/$tofile");
	try_dir("$todir/.log");
	try_rename("$fromdir/.log/$fromfile","$todir/.log/$tofile");
	try_dir("$todir/.note");
	try_rename("$fromdir/.note/$fromfile","$todir/.note/$tofile");
	try_dir("$todir/.lock");
	try_rename("$fromdir/.lock/$fromfile","$todir/.lock/$tofile");
	try_dir("$todir/.bak");
	for($i=0;$i<=$GLOBALS[gblNumBackups];$i++) {
		try_rename("$fromdir/.bak/$i/$fromfile","$todir/.bak/$i/$tofile");
	}
}


//////////////////////////////////////////////////////////////////

// recursivly delete directory

function rrmdir($dir) {
	$handle=opendir($dir);
	while ($file = readdir($handle)) {
		if ($file != "." && $file != "..") {
			if (is_dir("$dir/$file"))
				rrmdir("$dir/$file");
			else
				if (! @unlink("$dir/$file")) return(0);
		}
	}
	closedir($handle);
	return @rmdir($dir);
}

//////////////////////////////////////////////////////////////////

function ChangeLog($target,$msg) {

	global $gblFsRoot;
	$log=fopen("$gblFsRoot/.changelog","a+");
	if (substr($target,0,strlen($gblFsRoot)) == $gblFsRoot)
		$target=substr($target,strlen($gblFsRoot),strlen($target)-strlen($gblFsRoot));
	fputs($log,time()."\t$target\t$GLOBALS[gblUserName]\t$msg\n");
	fclose($log);

}

function DisplayChangeLog($day) {

	global $gblFsRoot;
	if (!file_exists("$gblFsRoot/.changelog")) return;
	$log=fopen("$gblFsRoot/.changelog","r");
	$logarr = array();
	while($line = fgetcsv($log,255,"\t")) {
		if ($day!=1 || ($day==1 && (time()-$line[0] < 24*60*60))) {
			array_unshift($logarr,array($line[0],$line[1],$line[2],$line[3]));
		}
	}
	fclose($log);
	$cl1=" class=LST"; $cl2="";
	print "<table border=0 width=100%>\n";
	while ($e = array_shift($logarr)) {
		$cl=$cl1; $cl1=$cl2; $cl2=$cl;
		$date = date("$GLOBALS[gblDateFmt]", $e[0]);
		$time = date("$GLOBALS[gblTimeFmt]", $e[0]);
		$dir = dirname($e[1]);
		$file = basename($e[1]);
		print "<tr><td$cl>$date</td><td$cl>$time</td><td$cl><a href=\"$GLOBALS[PHP_SELF]?D=".urlencode($dir)."\">$dir</a>/$file</td><td$cl>$e[2]</td><td$cl>$e[3]</td></tr>\n";
	}
	print "</table>";
	print "<p>".GifIcon(up)." Back to <a href=$GLOBALS[PHP_SELF]>front page</a>.</p>";
}

//////////////////////////////////////////////////////////////////

// MAIN PROGRAM
// ============
// query parameters: capital letters
// local functions : begin with capital letters
// global constants: begin with gbl

	$gblFilePerms = 0640 ;         // default for new files
	$gblDirPerms  = 0750 ;		// default for new dirs

	// phpinfo() ;
	// exit ;

	// forks before authentication: style sheet and hash
	// creation if password not yet set.
	if ($STYLE == "get") { CSS() ; exit ; }

	$fsScriptDir  = dirname($SCRIPT_FILENAME) ; 	
	// i.e. /home/httpd/html/docman

	// read user-defined configuration
	if (file_exists("$fsScriptDir/.docman.conf")) {
		include("$fsScriptDir/.docman.conf");
	}

	// where do we get users from?
	if (file_exists("$gblIncDir/$gblUsers.php")) {
		include("$gblIncDir/$gblUsers.php");
	} else {
		Error("Configuration error","Can't find user handling module at <tt>$gblIncDir/$gblUsers.php</tt> ! Please fix <tt>$fsScriptDir/.docman.conf</tt>");
	}

	// authentication failure
	if ( md5($PHP_AUTH_USER.$PHP_AUTH_PW) != $gblPw ||
		isset($relogin) && $gblPw == $relogin ) {
		header("WWW-authenticate: basic realm=\"$HTTP_HOST\"") ;
		header("HTTP/1.0 401 Unauthorized") ;
		NoEntry() ;
		exit ;
	}

	// get current directory relative to $gblFsRoot 
	$relDir = $DIR ;	// from POST
	if ($relDir == "") {	// not defined in POST ? 
		$relDir = urldecode($D) ;  // then use GET
	}	

	$relDir=stripSlashes($relDir);

	if ($relDir == "/") $relDir = "" ; 	
	// default : website root = ""

	if (strstr($relDir,"..")) Error("No updirs allowed");

	// full paths contain "fs" or "Fs". Paths realitve to root of
	// website contain "rel" or "Rel". The script won't let you 
	// edit anything above directory equal to http://server.com 
	// i.e. below $gblFsRoot.

	$relScriptDir = dirname($SCRIPT_NAME) ;  	
	// i.e. /docman

	// start on server root
//	$gblFsRoot = substr($fsScriptDir,0, strlen($fsScriptDir)-strlen($relScriptDir)) ;
	// or on script root
	$gblFsRoot = $fsScriptDir;
	// i.e. /home/httpd/html

	$fsDir = $gblFsRoot . $relDir ; // current directory
	if ( !is_dir($fsDir) ) Error("Dir not found",$relDir) ;

	if (isset($GLOBALS["HTTPS"]) && $GLOBALS["HTTPS"] == "on") {
		$webRoot  = "https://";
	} else {
		$webRoot  = "http://";
	}
	$webRoot .= $GLOBALS["HTTP_HOST"] . $relScriptDir;

	$FN=stripSlashes($FN);


	switch ($POSTACTION) {
	case "UPLOAD" :
		if (!is_writeable($fsDir)) Error("Write denied",$relDir) ;
		if (strstr($FN_name,"/")) 
			Error("Non-conforming filename") ;
		// TODO : should rather check for escapeshellcmds
		// but maybe RFC 18xx asserts safe filenames ....
		$source = $FN ;
		if (! file_exists($source)) {
			Error("You must select file with browse to upload it!");
		}
		if (! isset($FILENAME)) { 	// from update file
			$target = "$fsDir/$FN_name" ;
		} else {
			$target = "$fsDir/$FILENAME";
		}

		// backup old files first
		$dir=dirname($target);
		if (! file_exists($dir."/.bak")) {
			mkdir($dir."/.bak",0700);
		}
		if (! file_exists($dir."/.bak/$GLOBALS[gblNumBackups]")) {
			mkdir($dir."/.bak/$GLOBALS[gblNumBackups]",0700);
		}
		$file=basename($target);
		for($i=$GLOBALS[gblNumBackups]-1;$i>0;$i--) {
			MoveTo("$dir/.bak/$i/$file","$dir/.bak/".($i+1)."/");
		}
		MoveTo($target,$dir."/.bak/1/");

		copy($source,$target) ;
		chmod($target,$gblFilePerms) ;
		clearstatcache() ;
		Logit($target,"uploaded");
		if (isset($FILENAME)) {
			Unlock($target);
		}
		ChangeLog($target,"updated");
		break ;

	case "SAVE" :
		$path = $gblFsRoot . $RELPATH ;
		$path=stripSlashes($path);
		$writable = is_writeable($path) ;
		$legaldir = is_writeable(dirname($path)) ;
		$exists   = (file_exists($path)) ? 1 : 0 ; 
// check for legal extension here as well
	 	if (!($writable || (!$exists && $legaldir))) 
			Error("Write denied",$RELPATH) ;
		$fh = fopen($path, "w") ;
		$FILEDATA=stripSlashes($FILEDATA);
		fwrite($fh,$FILEDATA) ;
		fclose($fh) ;
		clearstatcache() ;
		Logit($path,"saved changes");
		ChangeLog($path,"saved changes");
		break ;

	case "CREATE" :
		// we know $fsDir exists
		if ($FN == "") break;		// no filename!
		if (!is_writeable($fsDir)) Error("Write denied",$relDir) ;
		$path = $fsDir . "/" . $FN ;  // file or dir to create
		$relPath = $relDir . "/" . $FN ;
		switch ( $T ) {
		case "D" :  // create a directory
			if ( ! @mkdir($path,$gblDirPerms) ) 
				Error("Mkdir failed",$relPath) ; // eg. if it exists
			clearstatcache() ;
			break ;
		case "F" :  // create a new file
// this functionality is doubled in DetailView().
// better keep it here altogether
// chmod perms to $gblFilePerms
			if ( file_exists($path) && !is_writeable($path) ) 
				Error("File not writable", $relPath) ;
			$fh = fopen($path, "w+") ;
			if ($fh) {
				fputs($fh,"\n");
				fclose($fh) ;
				LogIt($path,"file created");
			} else {
				Error("Creation of file $relPath failed -- $path");
			}
			$tstr = "$PHP_SELF?A=E&D=".urlencode($relDir)."&F=".urlencode($FN) ;
			header("Location: " . $tstr) ;
			ChangeLog($target,"created");
			exit ;
		}
		break ;

	case "DELETE" :  
		if ( $CONFIRM != "on" ) break ;

		$tstr  = "Attempt to delete non-existing object or " ;
		$tstr .= "insufficient privileges: " ;

		if ( $FN != "") {  // delete file
			$path =  $fsDir . "/" . $FN ;
		
			$dir=dirname($path);
			$file=basename($path);
			if (! file_exists("$dir/.del")) {
				mkdir("$dir/.del",0700);
			}

//			if ( ! @unlink($path) ) { 
			if ( ! rename($path,"$dir/.del/$file") ) { 
				Error("File delete failed", $tstr . $path) ; 
				Logit($path,"file delete failed");
				exit ; 
			} else {
				Logit($path,"file deleted");
				MoveTo("$dir/.log/$file","$dir/.del/.log/");
				MoveTo("$dir/.note/$file","$dir/.del/.note/");
				MoveTo("$dir/.lock/$file","$dir/.del/.lock/");
			}
		}
		else {  // delete directory
		  if ( ! @rrmdir($fsDir) ) {
		    Error("Rmdir failed", $tstr . $fsDir) ; 
		  }
		  else {
		    $relDir = dirname($relDir) ;  // move up
		  }
		}
		break ;

	case "UNDELETE" :  
		if ( $CONFIRM != "on" ) break ;

		if (substr($FN,0,4) != ".del") break ;
		$file=substr($FN,4,strlen($FN)-4);

		Logit("$fsDir/.del/$file","undeleted");
		MoveTo("$fsDir/.del/$file","$fsDir/");
		MoveTo("$fsDir/.del/.log/$file","$fsDir/.log/");
		MoveTo("$fsDir/.del/.note/$file","$fsDir/.note/");
		MoveTo("$fsDir/.del/.lock/$file","$fsDir/.lock/");

		break ;

	case "RENAME" :  
		if ( $CONFIRM != "on" ) break ;

		Logit("$fsDir/$FN","renamed $FN to $NEWNAME");
		safe_rename($fsDir,$FN,$NEWNAME);
		break ;

	case "NOTE" :  
		WriteNote("$fsDir/$FN","$NOTE");
		break ;

	case "UNLOCK" :  
		if ( $CONFIRM != "on" ) break ;
		Unlock("$fsDir/$FN");
		break ;

	default :
		// user hit "CANCEL" or undefined action
	}

	// common to all POSTs : redirect to directory view ($relDir)
	if ( $POSTACTION != "" ) { 
		$tstr = $PHP_SELF . "?D=" . urlencode($relDir) ;
		header("Location: " . $tstr) ;   
		exit ;
 	}
	
	// check for mode.. navigate, code display, upload, or detail?
	// $A=U : upload to path given in $D
	// $A=E : display detail of file $D/$F and edit
	// $A=C : display code in file $D/$F
	// $A=Co : checkout file $D/$F
	// $A=Ci : checkin file $D/$F
	// $A=V : view file (do nothing except log)
	// default : display directory $D

	switch ($A) {
	case "U" :
		// upload to $relDir
		if (!is_writeable($gblFsRoot . $relDir)) 
			Error("Write access denied",$relDir) ;
		$text  = "Use this page to upload a single " ;
		$text .= "file to <B>$HTTP_HOST</B>." ;
		StartHTML("(Upload Page)", $text) ;
		UploadPage($gblFsRoot, $relDir) ;
		EndHTML() ;
		exit ;
	case "E" :
		$F=stripSlashes($F);
		// detail of $relDir/$F
		if (is_file("$gblFsRoot/$relDir/$F") || is_dir("$gblFsRoot/$relDir/$F")) DetailPage($gblFsRoot, $relDir, $F) ;
		exit ;
	case "C" :
		$F=stripSlashes($F);
		// listing of $relDir/$F 
		DisplayCode($gblFsRoot, $relDir, $F) ;
		exit ;
	case "Co" :
		// checkout
		Lock("$gblFsRoot/$relDir/$F");
		header("Content-Disposition: attachment; filename=$F" );
		Header("Location: $webRoot".urlpath("$relDir/$F"));
		exit;
	case "Ci" :
		$F=stripSlashes($F);
		// upload && update to $relDir
		if (!is_writeable($gblFsRoot . $relDir)) 
			Error("Write access denied",$relDir) ;
		$text  = "Use this page to update a single " ;
		$text .= "file to <B>$HTTP_HOST</B>." ;
		StartHTML("(Update file Page)", $text) ;
		UploadPage($gblFsRoot, $relDir, $F) ;
		EndHTML() ;
		exit ;
	case "V" :
		// view
		LogIt("$gblFsRoot/$relDir/$F","viewed");
		header("Content-Disposition: attachment; filename=$F" );
		Header("Location: $webRoot".urlpath("$relDir/$F"));
		exit;
	case "Ch" :
		StartHTML("(File changes)","All changes chronologicaly...");
		DisplayChangeLog(0);	// all
		EndHTML() ;
		exit;
	case "Ch1" :
		StartHTML("(File changes)","Changes to files in last day...");
		DisplayChangeLog(1);
		EndHTML() ;
		exit;
	}

	// default: display directory $relDir
	Navigate($gblFsRoot,$relDir) ;	
	exit ;

	Error("Whooah!","By cartesian logic, this never happens") ;
?>
